iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
Modern Web

JS30 x 鐵人30 x MDN doc系列 第 3

[Day3] - CSS Variables(JS30 x 鐵人 30 x MDN)

  • 分享至 

  • xImage
  •  

實做一個網頁讓使用者能調整照片像框的粗度、顏色、模糊度

觀察 index-Start.html 可以發現有三個 input 分別控制顏色、模糊度、寬度

<h2>Update CSS Variables with <span class="hl">JS</span></h2>

<div class="controls">
  <label for="spacing">Spacing:</label>
  <input
    id="spacing"
    type="range"
    name="spacing"
    min="10"
    max="200"
    value="10"
    data-sizing="px"
  />

  <label for="blur">Blur:</label>
  <input
    id="blur"
    type="range"
    name="blur"
    min="0"
    max="25"
    value="10"
    data-sizing="px"
  />

  <label for="base">Base Color</label>
  <input id="base" type="color" name="base" value="#ffc600" />
</div>

<img src="https://source.unsplash.com/7bwQXzbF6KE/800x500" />

在看影片之前,我先使用了前兩天所學的渾身解數完成了這題,完成是完成了但發現根本沒學到今天題目的重點 CSS Variables

  1. 先說說我原本做法:
    (1)~(5)宣告了 5 個參數分別querySelector()取得三個控制閥、一個圖片容器、以及 h2 標題內的 JS 字樣的元素節點。
    (6)使用querySelectorAll()先取得所有的 input 元素節點並把它存放於 controlInputList 變數中。
    (7)以 controlInputList 使用forEach()將每個 input 節點都新增一個針對HTMLElement: input event的事件監聽器,當 input 值有變更時都會執行函式 changeStyle。
    (8)函式 changeStyle 中每次都做三種判斷:
    _ 如果變更的控制閥 id 等於"spacing"就使用控制閥現在的值去修改照片節點的border邊框粗度。
    _ 如果變更的控制閥 id 等於"blur"就使用控制閥現在的值去修改照片節點的filter:blur(?px)模糊度。 * 如果變更的控制閥 id 等於"color"就使用控制閥現在的值去修改照片節點的border邊框顏色、及 hl 節點的color字體顏色。
const spacingControl = document.querySelector("input#spacing");
const blurControl = document.querySelector("input#blur");
const colorControl = document.querySelector("input#base");
const imgContainer = document.querySelector("img");
const hl = document.querySelector(".hl");

const controlInputList = document.querySelectorAll("input");
controlInputList.forEach((input) => {
  input.addEventListener("input", changeStyle);
});

function changeStyle(e) {
  if (e.target.id === "spacing") {
    imgContainer.style.border = `${colorControl.value} ${e.target.value}px solid`;
  }
  if (e.target.id === "blur") {
    imgContainer.style.filter = `blur(${e.target.value}px)`;
  }
  if (e.target.id === "base") {
    imgContainer.style.border = `${e.target.value} ${spacingControl.value}px solid`;
    hl.style.color = `${colorControl.value}`;
  }
}
  1. 改寫開始,終於用到重頭戲CSS Variables,那麼要寫在哪裡就是一門學問,不用緊張 MDN 都教你了,我們使用代表文檔根元素(即<hrml>)的偽類:root,並以三個 input 的 id 當作變數名稱、value 當作初始值設定。
:root {
  --spacing: 10px;
  --blur: 0px;
  --base: #ffc600;
}
  1. 接著將需要用到這些 style 的元素使用var(-- 變數名)告訴 CSS 套用樣式時要呼叫這些變數。
    題外話:在使用var()時,後面可以帶入好幾個參數當作備用值,當第一個參數無效時,CSS則會自動套用第二個參數當作樣式顯示...以此類推,甚至可以寫成這樣「var(--a,var(--b,var(--c,red))」。
.hl {
  color: var(--base);
}
img {
  border: var(--spacing) var(--base) solid;
  filter: blur(var(--blur));
}
  1. 最後就是 Javascript,這次我們不用取得那麼多元素,只需要整個 input nodeList 每個都新增監聽器修改對應變數值,所有使用這個變數的都會跟著修改,是不是方便多了,程式碼也少了好幾行 👍

(1)使用querySelectorAll()先取得所有的 input 元素節點並把它存放於 controlInputList 變數中。
(2)以 controlInputList 使用forEach()將每個 input 節點都新增一個針對HTMLElement: input event的事件監聽器,當 input 值有變更時都會執行函式 changeStyle。
(3)函式 changeStyle:
_ 宣告一個代表單位的變數,如果 input 本身HTMLElement: dataset property有自定義 sizing 那就引用單位否則就是一個空字串。
_ document.documentElement 其實等於 document.querySelector("html")
Element.style.setProperty(propertyName, "value")其實也等於 Element.style.propertyName = "value"

//改用 CSS variables
const controlInputList = document.querySelectorAll("input");
controlInputList.forEach((input) => {
  input.addEventListener("input", changeStyle);
});

function changeStyle(e) {
  const unit = e.target.dataset.sizing ?? "";
  document.documentElement.style.setProperty(
    `--${e.target.id}`,
    `${e.target.value}${unit}`
  );
  //document.documentElement.style[`--${e.target.id}`] = `${e.target.value}${unit}`;
}

👉Github Demo 頁面 👈

👉 好想工作室 15th 鐵人賽看板 👈

參考資料

  1. Javascript 30 官網
    https://javascript30.com/
  2. MDN 官網
    https://developer.mozilla.org/en-US/

上一篇
[Day2] - JS and CSS Clock(JS30 x 鐵人 30 x MDN)
下一篇
[Day4] - Array Cardio part1(JS30 x 鐵人 30 x MDN)
系列文
JS30 x 鐵人30 x MDN doc30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言